home *** CD-ROM | disk | FTP | other *** search
- unit AccountExample;
-
- interface
-
- uses
- classes;
-
- type
-
- { forward declarations }
- TAccountLine = class;
-
- TSimpleAccount = class
- private
- FBalance: Currency;
- FBalanceCalculated: Boolean;
- FLines: TList;
- function CalculateBalance: Currency;
- function GetBalance: Currency;
- function GetAccountLine(Index: Integer): TAccountLine;
- function GetLineCount: Integer;
- protected
- function InternalGetAccountLine(Index: Integer): TAccountLine;
- procedure AssertInvariants; virtual;
- public
- constructor Create;
- destructor Destroy; override;
- function AddLine(const Text: string; Amount: Currency): TAccountLine;
-
- property Balance: Currency read GetBalance;
- property Lines[Index: Integer]: TAccountLine read GetAccountLine;
- property LineCount: Integer read GetLineCount;
- end;
-
- TAccountLine = class
- private
- FText: string;
- FAmount: Currency;
- procedure SetText(const Value: string);
- public
- constructor Create(const AText: string; AAmount: Currency);
- property Text: string read FText write SetText;
- property Amount: Currency read FAmount;
- end;
-
- const
- S_PreFailed = 'Pre-Condition failed: ';
- S_PostFailed = 'Post-Condition failed: ';
- S_InvFailed = 'Invariant-Condition failed: ';
-
- implementation
-
- uses
- contnrs;
-
- { TSimpleAccount }
-
- function TSimpleAccount.AddLine(const Text: string;
- Amount: Currency): TAccountLine;
-
- procedure AssertPre;
- begin
- AssertInvariants;
- Assert(Length(Text) > 0,S_PreFailed + 'Lenght(Text) must be > 0');
- Assert(Amount<> 0,S_PreFailed + 'Ammount must be <> 0');
- end;
-
- procedure AssertPost;
- begin
- AssertInvariants;
- Assert(Assigned(Result),'Result does not contain a valid AccountLine object');
- end;
-
- begin
- AssertPre;
- Result := TAccountLine.Create(Text,Amount);
- FLines.Add(Result);
- { uncomment the next line to fix AssertInvariants failure }
- FBalanceCalculated := False;
- AssertPost;
- end;
-
- procedure TSimpleAccount.AssertInvariants;
- begin
- if FBalanceCalculated then begin
- Assert(FBalance = CalculateBalance,S_InvFailed + 'Balance out of Sync');
- end;
- end;
-
- function TSimpleAccount.CalculateBalance: Currency;
- var
- I: Integer;
- begin
- Result := 0;
- for I := 0 to Pred(LineCount) do begin
- Result := Result + InternalGetAccountLine(I).Amount;
- end;
- end;
-
- constructor TSimpleAccount.Create;
- begin
- FLines := TObjectList.Create(True);
- end;
-
- destructor TSimpleAccount.Destroy;
- begin
- FLines.Free;
- inherited Destroy;
- end;
-
- function TSimpleAccount.GetAccountLine(Index: Integer): TAccountLine;
-
- procedure AssertPre;
- begin
- AssertInvariants;
- Assert((Index > -1) and (Index < LineCount),
- S_PreFailed + 'Index must be > -1 and < Count');
- end;
-
- begin
- AssertPre;
- Result := InternalGetAccountLine(Index);
- end;
-
- function TSimpleAccount.GetBalance: Currency;
- begin
- if not FBalanceCalculated then begin
- FBalance := CalculateBalance;
- FBalanceCalculated := True;
- end;
- Result := FBalance;
- end;
-
- function TSimpleAccount.GetLineCount: Integer;
- begin
- Result := FLines.Count;
- end;
-
- function TSimpleAccount.InternalGetAccountLine(
- Index: Integer): TAccountLine;
- begin
- Result := FLines[Index];
- end;
-
- { TAccountLine }
-
- constructor TAccountLine.Create(const AText: string; AAmount: Currency);
- begin
- FText := AText;
- FAmount := AAmount;
- end;
-
- procedure TAccountLine.SetText(const Value: string);
- begin
- FText := Value;
- end;
-
- end.
-